﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections;
using System.IO;
using System.Xml.Serialization;
using System.Diagnostics;
using Misiak;
using C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery;

namespace BlueBoss2
{
    //delegates
    public delegate void UpdateDiscoverBox(List<Device> d);
    public delegate void UpdateDeviceSeenList(WatchItem e);

    public partial class Form1 : Form
    {
        //various lists
        List<Device> deviceList = new List<Device>();
        WatchItemList watchList = new WatchItemList();
        ArrayList deviceSeenList = new ArrayList();

        //construct threads
        Thread DiscoverAllThread;
        Thread DiscoverDeviceThread;
                    
        // events used to stop worker thread
        ManualResetEvent EventStopThread;
        ManualResetEvent EventThreadStopped;

       
        public UpdateDiscoverBox ThreadUpdateDiscoverBox;
        public UpdateDeviceSeenList AddToDeviceSeenList;
        public UpdateDeviceSeenList RemoveFromDeviceSeenList;

        public Form1()
        {
            InitializeComponent();

            //read config file
            ReadXmlConfig();
            
            //start timer
            tmrMain.Interval = 10000; //10 seconds
            tmrMain.Enabled = true;
            tmrMain.Tick += new EventHandler(tmrMain_Tick);
            //setup discover all thread
            EventStopThread = new ManualResetEvent(false);
            EventThreadStopped = new ManualResetEvent(false);

            ThreadUpdateDiscoverBox = new UpdateDiscoverBox(this.UpdateDiscoverBox);
            AddToDeviceSeenList = new UpdateDeviceSeenList(this.AddDeviceSeenItem);
            RemoveFromDeviceSeenList = new UpdateDeviceSeenList(this.RemoveDeviceSeenItem);
        }

        void tmrMain_Tick(object sender, EventArgs e)
        {
           //10 seconds have passed
            foreach (WatchItem item in watchList.WatchItems)
            {
                //reset events
                EventStopThread.Reset();
                EventThreadStopped.Reset();

                //create workerthread to discover single device
                DiscoverDeviceThread = new Thread(new ParameterizedThreadStart(this.DiscoverDeviceWorkerThread));
                DiscoverDeviceThread.Name = "Single Device Watch Thread";
                DiscoverDeviceThread.Start(item);
            }
        }

        private void ReadXmlConfig()
        {
            FileInfo config = new FileInfo(System.Environment.CurrentDirectory + "\\bb.xml");

            if (config.Exists)
            {
                XmlSerializer s = new XmlSerializer(typeof(WatchItemList));
                watchList = new WatchItemList();
                //fix path
                TextReader r = new StreamReader(config.FullName);
                watchList = (WatchItemList)s.Deserialize(r);
                r.Close();

                foreach (WatchItem tmp in watchList.WatchItems)
                {
                    lbxWatchlist.Items.Add(tmp.DeviceName);
                }
            }
            else
            {
                watchList = new WatchItemList();
            }
        }

        private void WriteXmlConfig()
        {
            if (watchList.Count != 0)
            {
                XmlSerializer s = new XmlSerializer(typeof(WatchItemList));
                TextWriter w = new StreamWriter(System.Environment.CurrentDirectory + "\\bb.xml");
                s.Serialize(w, watchList);
                w.Close();
            }
            else
            {
                File.Delete(System.Environment.CurrentDirectory + "\\bb.xml");
            }
        }

        private void btnDiscover_Click(object sender, EventArgs e)
        {
            //execute thread to discoverall

            //disable button
            btnDiscover.Enabled = false;
            btnAddWatchlist.Enabled = false;
            btnDiscover.Text = "scanning..";
            EventStopThread.Reset();
            EventThreadStopped.Reset();

            // create worker thread instance for discovering all devices
            DiscoverAllThread = new Thread(new ThreadStart(this.DiscoverAllWorkerThread));
            DiscoverAllThread.Name = "Discovering Worker Thread";
            DiscoverAllThread.Start();
            lbxDevices.Items.Clear();

        }

        public void DiscoverAllWorkerThread()
        {
            WorkerThread tmpWorker;
            tmpWorker = new WorkerThread(EventStopThread, EventThreadStopped, this);
            tmpWorker.Run("AllDevices");  //hack to get dual functionality of run method
        }

        public void DiscoverDeviceWorkerThread(object x)
        {
            WatchItem item;
            item = (WatchItem)x;
            WorkerThread tmpWorker;
            tmpWorker = new WorkerThread(EventStopThread, EventThreadStopped, this, item);
            tmpWorker.Run("SingleDevice");
        }

        public void UpdateDiscoverBox(List<Device> x)
        {
            deviceList = x;
            if (deviceList != null)
            {
                foreach (Device s in deviceList)
                {
                    lbxDevices.Items.Add(s.Name);
                }
            }
            else
            {
                MessageBox.Show("No device was found.",
                                "Device Discovery", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            //reset button defaults
            btnDiscover.Text = "Discover";
            btnDiscover.Enabled = true;
        }

        private void lbxDevices_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbxDevices.SelectedIndex >-1)
            {
                btnAddWatchlist.Enabled = true;
            }
        }

        private void btnAddWatchlist_Click(object sender, EventArgs e)
        {
            //see if watchitem exits
            bool watchItemExists = false;
            foreach (WatchItem x in watchList.WatchItems)
            {
                if (lbxDevices.SelectedItem.ToString() == x.DeviceName)
                    watchItemExists = true;
            }
            //if it doesnt show form
            if (!watchItemExists)
            {
                this.Enabled = false;
                WatchItemForm itemForm = new WatchItemForm(this, lbxDevices.SelectedItem.ToString());
                itemForm.Show();
            }
            else
            {
                MessageBox.Show("Watch Item already exists!");
            }
        }

        public void AddWatchItem(WatchItem Item)
        {
            watchList.AddWatchItem(Item);
            lbxWatchlist.Items.Add(Item.DeviceName);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //need to kill active threads!
            if (DiscoverDeviceThread != null)
            {
                DiscoverDeviceThread.Abort();
            }
            if (DiscoverAllThread != null)
            {
                DiscoverAllThread.Abort();
            }

            //form closing, save watchlist to xml
            WriteXmlConfig();
        }

        private void lbxWatchlist_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbxWatchlist.SelectedIndex > -1)
            {
                btnEditWatchlist.Enabled = true;
                btnRemoveWatchlist.Enabled = true;
            }
            else
            {
                btnEditWatchlist.Enabled = false;
                btnRemoveWatchlist.Enabled = false;
            }
        }

        private void btnRemoveWatchlist_Click(object sender, EventArgs e)
        {
            //remove from watchlist and listbox
            foreach (WatchItem item in watchList.WatchItems)
            {
                if (item.DeviceName == lbxWatchlist.SelectedItem.ToString())
                {
                    watchList.RemoveWatchItem(item);
                    lbxWatchlist.Items.Remove(lbxWatchlist.SelectedItem);
                }
            }
            btnRemoveWatchlist.Enabled = false;
        }

        private void btnEditWatchlist_Click(object sender, EventArgs e)
        {
            foreach (WatchItem x in watchList.WatchItems)
            {
                if (lbxWatchlist.SelectedItem.ToString() == x.DeviceName)
                {
                    WatchItemForm itemForm = new WatchItemForm(this, x);
                    this.Enabled = false;
                    itemForm.Show();
                    watchList.RemoveWatchItem(x);
                    lbxWatchlist.Items.Remove(x.DeviceName);
                }
            }

        }
        public void AddDeviceSeenItem(WatchItem item)
        {
            //device is seen
            if (deviceSeenList.Count == 0)
            {
                deviceSeenList.Add(item);
                NotifyDeviceWindow(item);
            }
            else
            {
                for (int s = 0; s < deviceSeenList.Count; s++)
                {
                    WatchItem tmp;
                    tmp = (WatchItem)deviceSeenList[s];
                    if (item.DeviceName == tmp.DeviceName)
                    {
                        //already seen dont add or display
                        break;
                    }
                    else
                    {
                        deviceSeenList.Add(item);
                        NotifyDeviceWindow(item);
                    }
                }
            }
        }

        public void RemoveDeviceSeenItem(WatchItem item)
        {
            deviceSeenList.Remove(item);
        }


        public void NotifyDeviceWindow(WatchItem x)
        {
            NotifyWindow nw;
            nw = new NotifyWindow();
            //validate Alert Message
            if (x.AlertMessage == null)
            {
                nw.Text = x.DeviceName;
            }
            else
            {
                nw.Text = x.AlertMessage;
            }
            //validate picture
            if (x.ImagePath != null)
            {
                FileInfo imgfile = new FileInfo(x.ImagePath);
                if (imgfile.Exists)
                {
                    nw.PicturePath = x.ImagePath;
                }
                else
                {
                    MessageBox.Show("Image does not exist");
                }
            }
            nw.Notify();

            if (x.ProgramPath != null)
            {
                RunProcess(x.ProgramPath);
            }
        }

        public void RunProcess(String Path)
        {
            try
            {
                Process proc = new Process();
                proc.StartInfo.FileName =Path;
                proc.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Problem with executing process:" + ex.Message.ToString());
            }
        }

        private void niMain_DoubleClick(object sender, EventArgs e)
        {
            //show main form when notify icon is double clicked
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            //when form minimized hide (notify icon will take care of this)
            if (FormWindowState.Minimized == WindowState)
                Hide();
        }

        private void llblAuthor_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start(e.Link.LinkData.ToString());
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            llblAuthor.Links.Add(0, llblAuthor.Text.Length, "www.copyandwaste.com");
        }

        private void cmiExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}
